package com.xhwl.data.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhwl.common.dto.cent.sdata.AccountPersonalDTO;
import com.xhwl.common.dto.cent.sdata.AdminAccountDTO;
import com.xhwl.common.enums.CodeEnum;
import com.xhwl.common.enums.sdata.DevelopTypeEnum;
import com.xhwl.common.exception.DataException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.sdata.Account;
import com.xhwl.common.pojo.cent.sdata.AdminAccount;
import com.xhwl.common.pojo.cent.sdata.AdminAccountRole;
import com.xhwl.common.pojo.cent.sdata.Role;
import com.xhwl.common.pojo.cent.sdata.devplatform.Developer;
import com.xhwl.common.query.cent.AdminAccountQuery;
import com.xhwl.common.query.cent.sdata.AccountQuery;
import com.xhwl.common.utils.CentDataVerifyUtil;
import com.xhwl.common.utils.ValidatorUtil;
import com.xhwl.data.dao.IAdminAccountDao;
import com.xhwl.data.dao.IAdminAccountRoleDao;
import com.xhwl.data.dao.IPermissionDao;
import com.xhwl.data.dao.IRoleDao;
import com.xhwl.data.dao.devplatform.IDeveloperDao;
import com.xhwl.data.service.IAdminAccountRoleService;
import com.xhwl.data.service.IAdminAccountService;
import com.xhwl.data.service.IMessageCodeService;
import com.xhwl.data.util.Constant;
import com.xhwl.data.util.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: luyi
 * @Description:
 * @Date: Create in 2:37 下午 2020/9/25
 */
@Service
public class AdminAccountServiceImpl extends ServiceImpl<IAdminAccountDao, AdminAccount> implements IAdminAccountService {

    @Autowired
    private IAdminAccountDao adminAccountDao;

    @Autowired
    private IPermissionDao permissionDao;

    @Autowired
    private IAdminAccountRoleService adminAccountRoleService;

    @Autowired
    private IRoleDao roleDao;

    @Autowired
    private IAdminAccountRoleDao adminAccountRoleDao;

    @Autowired
    private IDeveloperDao developerDao;

    @Autowired
    IMessageCodeService messageCodeService;

    @Autowired
    RedisUtils redisUtils;

    private static final Logger log = LoggerFactory.getLogger(AdminAccountServiceImpl.class);

    /**
     * 根据登录名查找系统账号
     *
     * @param loginName
     * @return
     */
    @Override
    public AdminAccount findByLoginName(String loginName) {
        QueryWrapper<AdminAccount> adminAccountQueryWrapper = new QueryWrapper<>();
        adminAccountQueryWrapper.eq("login_name", loginName);
        List<AdminAccount> userList = adminAccountDao.selectList(adminAccountQueryWrapper);
        if (userList.isEmpty()) {
            throw new DataException("帐号不存在");
        } else if (userList.size() > 1) {
            log.warn("查找配置后台账号 ,发现存在异常数据,loginName={}，不唯一", loginName);
        }
        return userList.get(0);
    }

    /**
     * 创建系统账号
     *
     * @param adminAccount
     * @return
     */
    @Override
    public ResultJson<AdminAccount> createAdminAccount(AdminAccount adminAccount) {
        //1.账号数据判空
        if (StringUtils.isEmpty(adminAccount.getLoginName())) {
            return ResultJson.fail("账号不能为空");
        }
        if(StringUtils.isEmpty(adminAccount.getPassword())){
            String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 10);
            log.info("创建账号，设置为默认 {} ", substring);
            adminAccount.setPassword(substring);
        }
        //2.账号名验重
        if (checking(adminAccount)) {
            return ResultJson.fail("帐号已存在");
        }
        // 手机号校验
        if(phoneCheck(adminAccount)){
            return ResultJson.fail("手机号已存在");
        }
        //邮箱验重
        if(emailCheck(adminAccount)){
            return ResultJson.fail("邮箱已存在");
        }
        //3.密码加密 后插入
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String pwdEncode = bCryptPasswordEncoder.encode(adminAccount.getPassword());
        adminAccount.setPassword(pwdEncode);
        adminAccount.setIsDeleted(false);
        adminAccount.setStatus((short)1);
        adminAccount.setIsLogged(false);
        adminAccountDao.insert(adminAccount);
        return ResultJson.success(CodeEnum.SUCCESS.getCode(), "创建账号成功", adminAccount);

    }

    /**
     * false 通过校验
     * @param adminAccount
     * @return
     */
    private boolean phoneCheck(AdminAccount adminAccount) {
        QueryWrapper<AdminAccount> accountQueryWrapper = new QueryWrapper<>();
        accountQueryWrapper.eq("phone", adminAccount.getPhone());
        accountQueryWrapper.eq("develop_id", adminAccount.getDevelopId());
        if(null != adminAccount.getId()){
            accountQueryWrapper.ne("id", adminAccount.getId());
        }
        List<AdminAccount> adminAccounts = adminAccountDao.selectList(accountQueryWrapper);
        return !adminAccounts.isEmpty();
    }

    /**
     *false 通过效验
     * @param adminAccount
     * @return
     */
    private boolean emailCheck(AdminAccount adminAccount) {
        //邮箱可以为空
        if (StringUtils.isEmpty(adminAccount.getEmail())){
            return false;
        }
        QueryWrapper<AdminAccount> accountQueryWrapper = new QueryWrapper<>();
        accountQueryWrapper.eq("email", adminAccount.getEmail());
        accountQueryWrapper.eq("develop_id", adminAccount.getDevelopId());
        if(null != adminAccount.getId()){
            accountQueryWrapper.ne("id", adminAccount.getId());
        }
        List<AdminAccount> adminAccounts = adminAccountDao.selectList(accountQueryWrapper);
        return !adminAccounts.isEmpty();
    }

    @Override
    public ResultJson update(AdminAccountDTO adminAccount) {

        //账号名验重
        if (checking(adminAccount)) {
            return ResultJson.fail("帐号已存在");
        }
        // 手机号校验
        if(phoneCheck(adminAccount)){
            return ResultJson.fail("手机号已存在");
        }
        //邮箱验重
        if(emailCheck(adminAccount)){
            return ResultJson.fail("邮箱已存在");
        }
        if (StringUtils.isNotEmpty(adminAccount.getPassword())) {
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            String pwdEncode = bCryptPasswordEncoder.encode(adminAccount.getPassword());
            adminAccount.setPassword(pwdEncode);
        }
        adminAccountDao.updateById(adminAccount);

        // 更新账号角色信息 先删除 后新增
        if (!CollectionUtils.isEmpty(adminAccount.getRoleIds())){
            createAccountRole(adminAccount.getId(), adminAccount.getRoleIds());
        }
        return ResultJson.success("修改成功");
    }

    /**
     * 更新帐号的角色
     * @param id
     * @param roleIds
     */
    private void createAccountRole(Integer id, List<Integer> roleIds) {
        QueryWrapper<AdminAccountRole> adminAccountRoleQueryWrapper = new QueryWrapper<>();
        adminAccountRoleQueryWrapper.eq("admin_account_id", id);
        adminAccountRoleService.remove(adminAccountRoleQueryWrapper);
        if(CollectionUtils.isEmpty(roleIds)){
            throw new DataException("缺少角色信息");
        }
        QueryWrapper<Role> roleQueryWrapper = new QueryWrapper<>();
        roleQueryWrapper.select("id");
        roleQueryWrapper.in("id", roleIds);
        List<Role> list = roleDao.selectList(roleQueryWrapper);
        if(!CollectionUtils.isEmpty(list)){
            // 保存账号相关的角色信息
            List<AdminAccountRole> list1 = new ArrayList<>();
            for (Integer integer : list.stream().map(i -> i.getId()).collect(Collectors.toList())) {
                AdminAccountRole adminAccountRole  = new AdminAccountRole();
                adminAccountRole.setAdminAccountId(id);
                adminAccountRole.setRoleId(integer);
                list1.add(adminAccountRole);
            }
            adminAccountRoleService.saveBatch(list1);
        }

    }

    @Override
    public ResultJson delete(Integer id) {
        AdminAccount adminAccount = adminAccountDao.selectById(id);
        if (null!=adminAccount){
            adminAccountDao.deleteById(id);
            log.info("账号 被删除,id={},loginName={}", adminAccount.getId(),adminAccount.getLoginName());
        }
        // 删除关联的角色信息
        QueryWrapper<AdminAccountRole> adminAccountRoleQueryWrapper = new QueryWrapper<>();
        adminAccountRoleQueryWrapper.eq("admin_account_id", id);
        adminAccountRoleService.remove(adminAccountRoleQueryWrapper);
        return ResultJson.success("删除成功");
    }

    @Override
    public Page page(AdminAccountQuery adminAccountQuery, Page page) {
        QueryWrapper<AdminAccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "name", "login_name", "phone", "status", "is_deleted", "email", "updated_at AS updateAt", "created_at AS createAt");
        if (null != adminAccountQuery) {
            if (StringUtils.isNotEmpty(adminAccountQuery.keywords)) {
                queryWrapper.and(wq -> wq.like("login_name", adminAccountQuery.keywords)
                        .or().like("name", adminAccountQuery.keywords)
                        .or().like("phone", adminAccountQuery.keywords)
                        .or().like("email", adminAccountQuery.keywords));
            }
            if(null != adminAccountQuery.getRoleId()){
                QueryWrapper<AdminAccountRole> adminAccountQueryQueryWrapper = new QueryWrapper<>();
                adminAccountQueryQueryWrapper.eq("role_id", adminAccountQuery.getRoleId());
                List<AdminAccountRole> adminAccountRoles = adminAccountRoleDao.selectList(adminAccountQueryQueryWrapper);
                if(!adminAccountRoles.isEmpty()){
                    queryWrapper.in("id", adminAccountRoles.stream().map(i -> i.getAdminAccountId()).collect(Collectors.toList()));
                }else{
                    queryWrapper.eq("id", -1);
                }
            }
            if(!CollectionUtils.isEmpty(adminAccountQuery.getRoleIds())){
                QueryWrapper<AdminAccountRole> adminAccountQueryQueryWrapper = new QueryWrapper<>();
                adminAccountQueryQueryWrapper.in("role_id", adminAccountQuery.getRoleIds());
                List<AdminAccountRole> adminAccountRoles = adminAccountRoleDao.selectList(adminAccountQueryQueryWrapper);
                if(!adminAccountRoles.isEmpty()){
                    queryWrapper.in("id", adminAccountRoles.stream().map(i -> i.getAdminAccountId()).collect(Collectors.toList()));
                }else{
                    queryWrapper.eq("id", -1);
                }
            }
            if(null != adminAccountQuery.getStatus()){
                queryWrapper.eq("status", adminAccountQuery.getStatus());
            }
            if(null != adminAccountQuery.getDevelopId()){
                queryWrapper.eq("develop_id", adminAccountQuery.getDevelopId());
            }else{
                // 取系统默认的开发者信息，兼容旧接口
                log.warn("开发者信息为null, 从默认获取");
                QueryWrapper<Developer> developerQueryWrapper = new QueryWrapper<>();
                developerQueryWrapper.select("id");
                developerQueryWrapper.eq("type", DevelopTypeEnum.DEFAULT.id);
                Developer developer = developerDao.selectOne(developerQueryWrapper);
                if(null == developer){
                    log.error("缺少默认的开发者信息");
                }else{
                    queryWrapper.eq("develop_id", developer.getId());
                }
            }
        }
        Page page1 = adminAccountDao.selectPage(page, queryWrapper);
        return page1;
    }

    @Override
    @Transactional
    public ResultJson create(AdminAccountDTO adminAccountDTO) {
        ResultJson<AdminAccount> resultJson = createAdminAccount(adminAccountDTO);
        if(!resultJson.getState()){
            return resultJson;
        }
        List<Integer> roleIds = adminAccountDTO.getRoleIds();
        if(!CollectionUtils.isEmpty(roleIds)){
            // 更新账号角色信息 先删除 后新增
            createAccountRole(resultJson.getResult().getId(), adminAccountDTO.getRoleIds());
        }
        return ResultJson.success("操作成功", resultJson.getResult().getId());
    }

    @Override
    public List<AdminAccount> getList(AdminAccountQuery adminAccountQuery) {
        QueryWrapper<AdminAccount> query = new QueryWrapper<>();
        query.in(!CollectionUtils.isEmpty(adminAccountQuery.getIdList()), "id", adminAccountQuery.getIdList());
        if(null != adminAccountQuery.getRoleId()){
            QueryWrapper<AdminAccountRole> adminAccountRoleQueryWrapper = new QueryWrapper<>();
            adminAccountRoleQueryWrapper.eq("role_id", adminAccountQuery.getRoleId());
            List<AdminAccountRole> list = adminAccountRoleService.list(adminAccountRoleQueryWrapper);
            if(CollectionUtils.isEmpty(list)){
                query.eq("id", -1);
            }else{
                query.in("id", list.stream().map(i -> i.getAdminAccountId()).collect(Collectors.toList()));
            }
        }
        List<AdminAccount> adminAccounts = adminAccountDao.selectList(query);
        return adminAccounts;
    }

    @Override
    public ResultJson verifyPwd(Integer id, String pwd) {
        AdminAccount adminAccount = adminAccountDao.selectById(id);
        if(null == adminAccount){
            return ResultJson.fail("帐号不存在");
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        boolean matches = passwordEncoder.matches(pwd, adminAccount.getPassword());
        return matches ? ResultJson.success() : ResultJson.fail("密码错误");
    }

    @Override
    public ResultJson modifyPhone(AdminAccount adminAccount, AccountPersonalDTO accountPersonalDTO) {
        if (null == adminAccount.getIndustryId()) {
            return ResultJson.fail("缺少业态信息");
        }
        if (null == adminAccount.getId()){
            return ResultJson.fail("缺少账号信息");
        }
        ResultJson resultJson = null;
        String phone = Optional.ofNullable(accountPersonalDTO.getPhone()).orElseThrow(() -> new DataException("手机号不能为空"));
        String msgCode = Optional.ofNullable(accountPersonalDTO.getMsgCode()).orElseThrow(() -> new DataException("短信验证码不能为空"));
        //短信验证码校验
        resultJson = messageCodeService.phoneMsgCodeVerify(String.valueOf(adminAccount.getIndustryId()), phone, msgCode, true);
        if (CodeEnum.SUCCESS.code != resultJson.getCode()) {
            return resultJson;
        }
        redisUtils.remove(adminAccount.getIndustryId() + "_" + Constant.MSG_CODE_PREFIX + phone);
        //需要修改手机号
        CentDataVerifyUtil.phoneVerify(phone);
        //校验手机号开发者下唯一
        if(phoneCheck(adminAccount)){
            return ResultJson.fail("手机号已存在");
        }
        AdminAccountDTO adminAccountDTO = new AdminAccountDTO();
        adminAccountDTO.setId(adminAccount.getId());
        adminAccountDTO.setPhone(phone);

        adminAccountDao.updateById(adminAccountDTO);
        return ResultJson.success("修改成功");
    }

    @Override
    public ResultJson modifyPwd(Integer id, String pwd) {
        if (null == id) {
            throw new DataException("缺少账号信息");
        }
        AdminAccount accountDb = this.getById(id);
        if (Objects.isNull(accountDb)) {
            throw new DataException("缺少账号信息");
        }
        if (StringUtils.isNotEmpty(accountDb.getLoginName()) && StringUtils.isNotEmpty(pwd)) {
            if (accountDb.getLoginName().equals(pwd)) {
                log.info("密码与用户名重复,账号id={}", id);
                throw new DataException("密码格式错误");
            }
        }
        //密码校验
        CentDataVerifyUtil.pwdVerify(pwd);
        AdminAccount account = new AdminAccount();
        account.setId(id);
        account.setIsLogged(true);
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        //密码加密
        String pwdEncode = bCryptPasswordEncoder.encode(pwd);
        account.setPassword(pwdEncode);
        UpdateWrapper<AdminAccount> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);
        int effectNumUpdate = adminAccountDao.update(account, updateWrapper);
        if (1 != effectNumUpdate) {
            throw new DataException("修改密码失败");
        }
        return ResultJson.success("修改成功");
    }

    /**
     * 校验系统账号 是否重名
     *
     * @param adminAccount
     * @return
     */
    private Boolean checking(AdminAccount adminAccount) {
        QueryWrapper<AdminAccount> adminAccountQueryWrapper = new QueryWrapper<>();
        adminAccountQueryWrapper.select("id");
        adminAccountQueryWrapper.eq("login_name", adminAccount.getLoginName());
        adminAccountQueryWrapper.eq("develop_id", adminAccount.getDevelopId());
        if (null != adminAccount.getId()) {
            adminAccountQueryWrapper.ne("id", adminAccount.getId());
        }
        return null != adminAccountDao.selectOne(adminAccountQueryWrapper);
    }

//    private ResultJson modifyPersonalInfo(AdminAccount adminAccount){
//        if (null == adminAccount.getId()){
//            return ResultJson.fail("缺少账号信息");
//        }
//        AdminAccount adminAccount1 =
//        return ResultJson.success("修改成功");
//    }
}
